package fm.yichenet.controller;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import fm.controller.BaseController;
import fm.dto.NeiyiUser;
import fm.entity.OrderGood;
import fm.entityEnum.OrderEnum;
import fm.exception.BizException;
import fm.huanxin.service.MessageService;
import fm.nio.SemaphoreExecutor;
import fm.yichenet.mongo.service.ExpressService;
import fm.yichenet.mongo.service.GoodMgrService;
import fm.yichenet.mongo.service.UserAddressService;
import fm.yichenet.service.OrderService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.net.URLDecoder;
import java.util.*;
import java.util.concurrent.CountDownLatch;

/**
 * Created by CM on 2017/6/23.
 */
@Controller
@RequestMapping("/order")
public class OrderController extends BaseController {
    private static final Logger LOGGER = LoggerFactory.getLogger(OrderController.class);

    @Autowired
    OrderService orderService;
    @Autowired
    MessageService messageService;

    @ResponseBody
    @RequestMapping("/cancel")
    public Map cancelOrder(String orderId) {
        Map res = new HashMap();
        try {
            orderService.cancelOrder(orderId);
            this.success(res);
        } catch (BizException ex) {
            LOGGER.error("occur business error", ex);
            this.failed(res, ex.getMessage());
        } catch (Exception ex) {
            LOGGER.error("occur un-expected error", ex);
            this.failed(res, "服务器发生未知错误，请稍后再试或者联系管理员解决！");
        }
        return res;
    }


    @ResponseBody
    @RequestMapping("/refunds")
    public Map refundsOrder(String reason, Double amount, String orderId) {
        Map res = new HashMap();
        try {
            orderService.refundsOrder(orderId, reason, amount);
            this.success(res);
        } catch (BizException ex) {
            LOGGER.error("occur business error", ex);
            this.failed(res, ex.getMessage());
        } catch (Exception ex) {
            LOGGER.error("occur un-expected error", ex);
            this.failed(res, "服务器发生未知错误，请稍后再试或者联系管理员解决！");
        }
        return res;
    }


    @ResponseBody
    @RequestMapping("/refunds/deal")
    public Map refundsDealOrder(Integer status, String reason, String orderId) {
        Map res = new HashMap();
        try {
            orderService.refundsOrderDeal(orderId, reason, status);
            this.success(res);
        } catch (BizException ex) {
            LOGGER.error("occur business error", ex);
            this.failed(res, ex.getMessage());
        } catch (Exception ex) {
            LOGGER.error("occur un-expected error", ex);
            this.failed(res, "服务器发生未知错误，请稍后再试或者联系管理员解决！");
        }
        return res;
    }

    @ResponseBody
    @RequestMapping("/post")
    public Map postOrder(final String orderId, String expressNo) {
        Map res = new HashMap();
        try {
            orderService.postOrder(orderId, expressNo);
            OrderGood orderGood = orderService.getOrderById(orderId);
            String userId = orderGood.getUserId();
            if (userId != null) {
                String goodId = orderGood.getGoodId();
                Map param = new HashMap();
                param.put("good_id", goodId);
                try {
                    DBObject goodInfo = goodMgrService.getGood(param);
                    String msg = "您的购买的【" + goodInfo.get("goodName") + "】已经发货拉，物流单号："
                            + expressNo + ",请注意保持联系方式畅通，及时收货！";
                    messageService.addSystemMessage("wx_" + userId, msg);
                } catch (Exception e) {
                    LOGGER.error("获取商品信息发生错误,取消发送环信信息:", e);
                }
            }
            this.success(res);
        } catch (BizException ex) {
            LOGGER.error("occur business error", ex);
            this.failed(res, ex.getMessage());
        } catch (Exception ex) {
            LOGGER.error("occur un-expected error", ex);
            this.failed(res, "服务器发生未知错误，请稍后再试或者联系管理员解决！");
        }
        return res;
    }

    @ResponseBody
    @RequestMapping("/modify/price")
    public Map modifyPrice(Double sumPrice, String remarks, String orderId) {
        Map res = new HashMap();
        try {

            OrderGood orderGood = orderService.getOrderById(orderId);
            if (orderGood == null) {
                throw new BizException("未找到对应的订单信息，修改价格失败!");
            }
            String userId = orderGood.getUserId();

            orderService.updateOrderPrice(sumPrice, URLDecoder.decode(remarks, "UTF-8"), orderId);

            if (userId != null) {
                String goodId = orderGood.getGoodId();
                Map param = new HashMap();
                param.put("good_id", goodId);
                try {
                    DBObject goodInfo = goodMgrService.getGood(param);
                    String msg = "您的购买的:" + goodInfo.get("goodName") + "相关订单价格已经被修改，请注意核对，并及时付款！";
                    messageService.addSystemMessage("wx_" + userId, msg);
                } catch (Exception e) {
                    LOGGER.error("获取商品信息发生错误,取消发送环信信息:", e);
                }
            }
            this.success(res);
        } catch (BizException ex) {
            LOGGER.error("occur business error", ex);
            this.failed(res, ex.getMessage());
        } catch (Exception ex) {
            LOGGER.error("occur un-expected error", ex);
            this.failed(res, "服务器发生未知错误，请稍后再试或者联系管理员解决！");
        }
        return res;
    }


    @ResponseBody
    @RequestMapping("/user/list")
    public Map getUserOrders(String userId, OrderEnum status,
                             @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                             @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
        Map res = new HashMap();
        try {

            List<OrderGood> data = orderService.getUserOrder(status, userId, pageNum, pageSize);
            long count = orderService.countUserOrder(status, userId);
            HashMap dataMap = new HashMap();
            dataMap.put("list", data);
            dataMap.put("total", count);
            res.put("data", dataMap);
            this.success(res);
        } catch (BizException ex) {
            LOGGER.error("occur business error", ex);
            this.failed(res, ex.getMessage());
        } catch (Exception ex) {
            LOGGER.error("occur un-expected error", ex);
            this.failed(res, "服务器发生未知错误，请稍后再试或者联系管理员解决！");
        }
        return res;
    }


    @ResponseBody
    @RequestMapping("/shop/list")
    public Map getShopOrders(String shopId, OrderEnum status, Integer refundStatus,
                             @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                             @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
        Map res = new HashMap();
        try {
            List<OrderGood> data = orderService.getShopOrder(status, shopId, refundStatus, pageNum, pageSize);
            long count = orderService.countShopOrder(status, shopId);
            HashMap dataMap = new HashMap();
            dataMap.put("list", data);
            dataMap.put("total", count);
            res.put("data", dataMap);
            this.success(res);
        } catch (BizException ex) {
            LOGGER.error("occur business error", ex);
            this.failed(res, ex.getMessage());
        } catch (Exception ex) {
            LOGGER.error("occur un-expected error", ex);
            this.failed(res, "服务器发生未知错误，请稍后再试或者联系管理员解决！");
        }
        return res;
    }


    @ResponseBody
    @RequestMapping("/user/list/full")
    public Map getUserFullOrders(String userId, OrderEnum status,
                                 @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                                 @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
        Map res = new HashMap();
        try {
            List<OrderGood> data = orderService.getUserOrder(status, userId, pageNum, pageSize);
            long count = orderService.countUserOrder(status, userId);
            final List<Map<String, Object>> orderInfos = fillOrderInfos(data);

            HashMap dataMap = new HashMap();


            //再进行一次排序
            Collections.sort(orderInfos, new Comparator<Map<String, Object>>() {
                @Override
                public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                    OrderGood order = (OrderGood) o1.get("order");
                    OrderGood order1 = (OrderGood) o2.get("order");
                    return (order.getCreateTime().getTime() - order1.getCreateTime().getTime() >= 0) ? -1 : 1;
                }
            });


            dataMap.put("list", orderInfos);
            dataMap.put("total", count);
            res.put("data", dataMap);
            this.success(res);
        } catch (BizException ex) {
            LOGGER.error("occur business error", ex);
            this.failed(res, ex.getMessage());
        } catch (Exception ex) {
            LOGGER.error("occur un-expected error", ex);
            this.failed(res, "服务器发生未知错误，请稍后再试或者联系管理员解决！");
        }
        return res;
    }

    @Autowired
    UserAddressService userAddressService;
    @Autowired
    ExpressService expressService;
    @Autowired
    fm.mongoService.UserService userService;
    @Autowired
    GoodMgrService goodMgrService;

    @ResponseBody
    @RequestMapping("/shop/list/full")
    public Map getFullShopOrders(final String shopId, OrderEnum status, Integer refundStatus,
                                 @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
                                 @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
        Map res = new HashMap();
        try {
            List<OrderGood> data = orderService.getShopOrder(status, shopId, refundStatus, pageNum, pageSize);
            long count = orderService.countShopOrder(status, shopId);
            List<Map<String, Object>> orderInfos = fillOrderInfos(data);

            HashMap dataMap = new HashMap();

            //再进行一次排序
            Collections.sort(orderInfos, new Comparator<Map<String, Object>>() {
                @Override
                public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                    OrderGood order = (OrderGood) o1.get("order");
                    OrderGood order1 = (OrderGood) o2.get("order");
                    return (order.getCreateTime().getTime() - order1.getCreateTime().getTime() >= 0) ? -1 : 1;
                }
            });


            dataMap.put("list", orderInfos);
            dataMap.put("total", count);
            res.put("data", dataMap);
            this.success(res);
        } catch (BizException ex) {
            LOGGER.error("occur business error", ex);
            this.failed(res, ex.getMessage());
        } catch (Exception ex) {
            LOGGER.error("occur un-expected error", ex);
            this.failed(res, "服务器发生未知错误，请稍后再试或者联系管理员解决！");
        }
        return res;
    }


    private List<Map<String, Object>> fillOrderInfos(List<OrderGood> data) throws InterruptedException {
        final List<Map<String, Object>> orderInfos = new ArrayList<>();

        if (CollectionUtils.isNotEmpty(data)) {
            SemaphoreExecutor executor = new SemaphoreExecutor(data.size(), "fillOrderInfoThread");
            final CountDownLatch cdl = new CountDownLatch(data.size());

            for (final OrderGood order : data) {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Map<String, Object> item = new HashMap<>();
                            item.put("order", order);

                            String goodId = order.getGoodId();
                            if (StringUtils.isNotEmpty(goodId)) {
                                DBObject good = goodMgrService.getGood(new BasicDBObject("good_id", goodId).toMap());
                                item.put("good", good);

                                //添加订单评论详情
                                DBObject comment = goodMgrService.getOrderComment(order.getId(), order.getUserId());
                                if (comment != null) {
                                    item.put("comment", comment);
                                }
                            }

                            String expressId = order.getExpressId();
                            if (StringUtils.isNotEmpty(expressId)) {
                                DBObject express = expressService.getExpress(expressId);
                                item.put("express", express);
                            }

                            String addressId = order.getAddressId();
                            if (StringUtils.isNotEmpty(addressId)) {
                                DBObject address = userAddressService.getById(addressId);
                                item.put("address", address);
                            }
                            String shopId = order.getShopId();

                            if (shopId != null) {
                                NeiyiUser user = userService.getById(shopId);
                                HashMap shop = new HashMap();
                                shop.put("shopName", user.getCompanyName());
                                shop.put("shopId", shopId);
                                shop.put("loc", user.getLat() + "," + user.getLng());
                                shop.put("address", user.getUserAdd().getProvince() + "," + user.getUserAdd().getCity() + "," + user.getUserAdd().getDetailAddress());
                                shop.put("headimgurl", user.getUserLogo());
                                item.put("shop", shop);
                            }
                            orderInfos.add(item);
                        } catch (Exception e) {
                            LOGGER.info("获取商户订单发生错误：", e);
                        } finally {
                            cdl.countDown();
                        }

                    }
                });
            }
            cdl.await();

        }

        return orderInfos;

    }
}
